package org.rambadger.command.resource.util;

import com.google.common.base.Strings;
import com.google.common.io.ByteStreams;
import com.google.common.io.InputSupplier;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile;

import com.sun.jersey.multipart.FormDataBodyPart;
import org.bson.types.ObjectId;
import org.rambadger.command.UploadConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;

import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;

public class UploadHelper {
    private static final Logger log = LoggerFactory.getLogger(UploadHelper.class);
    GridFS gridFS;
    UploadConfiguration uploadConfig;


    public UploadHelper(GridFS gridFS, UploadConfiguration uploadConfig) {
        this.gridFS = gridFS;
        this.uploadConfig = uploadConfig;
    }

    //YOU STILL HAVE TO CALL SAVE!!!
    public GridFSInputFile process(final FormDataBodyPart body) {
        String filename = getFilename(body);
        if (Strings.isNullOrEmpty(filename)) throw new WebApplicationException(Response.Status.BAD_REQUEST);
        try {
            long length = ByteStreams.length(new InputSupplier<InputStream>() {
                @Override
                public InputStream getInput() throws IOException {
                    return body.getEntityAs(InputStream.class);
                }
            });
            if (length > uploadConfig.getMaxFileSize()) {
                log.error("Uploaded file too large. %l > %l", length, uploadConfig.getMaxFileSize());
                throw new WebApplicationException(413 /*Request Entity Too Large*/);
            }
        } catch (IOException e) {
            log.error("Failed to handle file upload", e);
            throw new WebApplicationException(INTERNAL_SERVER_ERROR);
        }

        GridFSInputFile file = gridFS.createFile(body.getEntityAs(InputStream.class), filename, true);
        try {
            file.saveChunks();
        } catch (IOException e) {
            log.error("Failed to handle file upload", e);
            deleteFile(file);
            throw new WebApplicationException(INTERNAL_SERVER_ERROR);
        }

        return file;
    }

    public static String getFilename(FormDataBodyPart body) {
        return body.getContentDisposition().getFileName();
    }

    public void deleteFile(GridFSDBFile file) {
        deleteFile(file.getId());
    }

    public void deleteFile(Object id) {
        ObjectId safeId = ObjectId.massageToObjectId(id);
        gridFS.remove(safeId);
    }
}
